#include "modeledit.h"
#include "ui_modeledit.h"
#include "myeeprom.h"
#include "helpers.h"
#include "edge.h"
#include "node.h"
#include "mixerdialog.h"
#include "burnconfigdialog.h"
#include "avroutputdialog.h"

#include <QtGui>

#define BC_BIT_RUD (0x01)
#define BC_BIT_ELE (0x02)
#define BC_BIT_THR (0x04)
#define BC_BIT_AIL (0x08)
#define BC_BIT_P1  (0x10)
#define BC_BIT_P2  (0x20)
#define BC_BIT_P3  (0x40)

#define RUD  (1)
#define ELE  (2)
#define THR  (3)
#define AIL  (4)

#define GFX_MARGIN 16

#define ALARM_GREATER(channel, alarm) ((eeData.frsky.channels[channel].alarms_greater >> alarm) & 1)
#define ALARM_LEVEL(channel, alarm) ((eeData.frsky.channels[channel].alarms_level >> (2*alarm)) & 3)


ModelEdit::ModelEdit(EEPROMData *md,  QWidget *parent) : QDialog(parent),
    ui(new Ui::ModelEdit)
{
    memcpy(&eeData, md, sizeof(EEPROMData));
    ui->setupUi(this);

    switchEditLock = false;

    setupMixerListWidget();

    QSettings settings("pipofig", "pipo");
    ui->tabWidget->setCurrentIndex(settings.value("modelEditTab", 0).toInt());

//    QRegExp rx(CHAR_FOR_NAMES_REGEX);
//    ui->modelNameLE->setValidator(new QRegExpValidator(rx, this));

    tabKPID();
    tabMixes();
    tabLimits();
    tabCurves();
    tabSwitches();
    tabSafetySwitches();

    ui->curvePreview->setMinimumWidth(260);
    ui->curvePreview->setMinimumHeight(260);

    resizeEvent();  // draws the curves and Expo

}


ModelEdit::~ModelEdit()
{
    delete ui;
}

void ModelEdit::setupMixerListWidget()
{
    MixerlistWidget = new MixersList(this);
    QPushButton * qbUp = new QPushButton(this);
    QPushButton * qbDown = new QPushButton(this);
    QPushButton * qbClear = new QPushButton(this);

    qbUp->setText("Move Up");
    qbUp->setIcon(QIcon(":/images/moveup.png"));
    qbUp->setShortcut(QKeySequence(tr("Ctrl+Up")));
    qbDown->setText("Move Down");
    qbDown->setIcon(QIcon(":/images/movedown.png"));
    qbDown->setShortcut(QKeySequence(tr("Ctrl+Down")));
    qbClear->setText("Clear Mixes");
    qbClear->setIcon(QIcon(":/images/clear.png"));

    ui->mixersLayout->addWidget(MixerlistWidget,1,1,1,3);
    ui->mixersLayout->addWidget(qbUp,2,1);
    ui->mixersLayout->addWidget(qbClear,2,2);
    ui->mixersLayout->addWidget(qbDown,2,3);

    connect(MixerlistWidget,SIGNAL(customContextMenuRequested(QPoint)),this,SLOT(mixerlistWidget_customContextMenuRequested(QPoint)));
    connect(MixerlistWidget,SIGNAL(doubleClicked(QModelIndex)),this,SLOT(mixerlistWidget_doubleClicked(QModelIndex)));
    connect(MixerlistWidget,SIGNAL(mimeDropped(int,const QMimeData*,Qt::DropAction)),this,SLOT(mimeDropped(int,const QMimeData*,Qt::DropAction)));

    connect(qbUp,SIGNAL(pressed()),SLOT(moveMixUp()));
    connect(qbDown,SIGNAL(pressed()),SLOT(moveMixDown()));
    connect(qbClear,SIGNAL(pressed()),SLOT(clearMixes()));

    connect(MixerlistWidget,SIGNAL(keyWasPressed(QKeyEvent*)), this, SLOT(mixerlistWidget_KeyPress(QKeyEvent*)));
}

void ModelEdit::resizeEvent(QResizeEvent *event)
{

    if(ui->curvePreview->scene())
    {
        QRect qr = ui->curvePreview->contentsRect();
        ui->curvePreview->scene()->setSceneRect(GFX_MARGIN, GFX_MARGIN, qr.width()-GFX_MARGIN*2, qr.height()-GFX_MARGIN*2);
        drawCurve();
    }

    QDialog::resizeEvent(event);

}

void ModelEdit::applyBaseTemplate()
{
    clearMixes(false);
//    applyTemplate(0);
    updateSettings();
    tabMixes();
}

void ModelEdit::updateSettings()
{
    emit modelValuesChanged(this);
}

void ModelEdit::refreshList()
{
    //refresh KPID
    for(int i=0; i<MAX_KPID; i++)
    {
        kpidKp[i]->blockSignals(true);
        kpidKi[i]->blockSignals(true);
        kpidKd[i]->blockSignals(true);

        kpidKp[i]->setValue(eeData.kpid[i].kp);
        kpidKi[i]->setValue(eeData.kpid[i].ki);
        kpidKd[i]->setValue(eeData.kpid[i].kd);

        kpidKp[i]->blockSignals(false);
        kpidKi[i]->blockSignals(false);
        kpidKd[i]->blockSignals(false);
    }

    //refresh Limits
    for(int i=0; i<NUM_CHNOUT; i++)
    {
        qsbLimitsMin[i]->blockSignals(true);
        qsbLimitsMax[i]->blockSignals(true);
        qsbLimitsPeriod[i]->blockSignals(true);
        qsbLimitsInv[i]->blockSignals(true);

        qsbLimitsMin[i]->setValue((double)eeData.limitData[i].min/1000.0f);
        qsbLimitsMax[i]->setValue((double)eeData.limitData[i].max/1000.0f);
        qsbLimitsPeriod[i]->setValue((double)eeData.limitData[i].period/1000.0f);
        qsbLimitsInv[i]->setChecked(eeData.limitData[i].revert);

        qsbLimitsMin[i]->blockSignals(false);
        qsbLimitsMax[i]->blockSignals(false);
        qsbLimitsPeriod[i]->blockSignals(false);
        qsbLimitsInv[i]->blockSignals(false);
    }

    //refresh Switches
    //refresh Safety

    //refresh Mixes
    tabMixes();

    //refresh Curves
    updateCurvesTab();
}

void ModelEdit::kpidEdited()
{
    //copy pid data
    for(int i=0; i<MAX_KPID; i++)
    {
        eeData.kpid[i].kp = kpidKp[i]->value();
        eeData.kpid[i].ki = kpidKi[i]->value();
        eeData.kpid[i].kd = kpidKd[i]->value();
    }

    updateSettings();
}

void ModelEdit::limitEdited()
{
    for(int i=0; i<NUM_CHNOUT; i++)
    {
        eeData.limitData[i].min = round(qsbLimitsMin[i]->value()*1000);
        eeData.limitData[i].max = round(qsbLimitsMax[i]->value()*1000);
        eeData.limitData[i].period = round(qsbLimitsPeriod[i]->value()*1000);
        eeData.limitData[i].revert = qsbLimitsInv[i]->isChecked();
    }

    updateSettings();
}


void ModelEdit::on_tabWidget_currentChanged(int index)
{
    QSettings settings("pipofig", "pipo");
    settings.setValue("modelEditTab",index);//ui->tabWidget->currentIndex());
}


void ModelEdit::tabKPID()
{
    for(int i=0; i<MAX_KPID; i++)
    {
        kpidKp[i] = new QSpinBox(this);
        kpidKp[i]->setValue(eeData.kpid[i].kp);
        kpidKp[i]->setMinimum(0);
        kpidKp[i]->setMaximum(0xFFFF);
        kpidKp[i]->setAlignment(Qt::AlignRight);
        connect(kpidKp[i],SIGNAL(editingFinished()),this,SLOT(kpidEdited()));
        ui->gridLayout_2->addWidget(kpidKp[i],i+1,1);

        kpidKi[i] = new QSpinBox(this);
        kpidKi[i]->setValue(eeData.kpid[i].ki);
        kpidKi[i]->setMinimum(0);
        kpidKi[i]->setMaximum(0xFFFF);
        kpidKi[i]->setAlignment(Qt::AlignRight);
        connect(kpidKi[i],SIGNAL(editingFinished()),this,SLOT(kpidEdited()));
        ui->gridLayout_2->addWidget(kpidKi[i],i+1,2);

        kpidKd[i] = new QSpinBox(this);
        kpidKd[i]->setValue(eeData.kpid[i].kd);
        kpidKd[i]->setMinimum(0);
        kpidKd[i]->setMaximum(0xFFFF);
        kpidKd[i]->setAlignment(Qt::AlignRight);
        connect(kpidKd[i],SIGNAL(editingFinished()),this,SLOT(kpidEdited()));
        ui->gridLayout_2->addWidget(kpidKd[i],i+1,3);
    }
}


void ModelEdit::tabMixes()
{
    // curDest -> destination channel
    // i -> mixer number
    QByteArray qba;
    MixerlistWidget->clear();
    int curDest = 0;
    int i;
    for(i=0; i<MAX_MIXERS; i++)
    {
        MixData *md = &eeData.mixData[i];
        if((md->destCh==0) || (md->destCh>NUM_XCHNOUT)) break;
        QString str = "";
        while(curDest<(md->destCh-1))
        {
            curDest++;
            str = getDestStr(curDest);
            qba.clear();
            qba.append((quint8)-curDest);
            QListWidgetItem *itm = new QListWidgetItem(str);
            itm->setData(Qt::UserRole,qba);
            MixerlistWidget->addItem(itm);
        }

        if(curDest!=md->destCh)
        {
            str = getDestStr(md->destCh);
            curDest=md->destCh;
        }
        else
            str = "     ";

        switch(md->mltpx)
        {
        case (1): str += " *"; break;
        case (2): str += " R"; break;
        default:  str += "  "; break;
        };

        str += QString(" %1*").arg((double)md->weight/256.0f, 0, 'f', 2);//.rightJustified(6,' ');

        str += getSourceStr(md->srcType);
        str += QString("%1").arg(md->srcNum,2,10,QChar('0'));

        if(md->swtch) str += tr(" Switch(") + getSWName(md->swtch) + ")";
//        if(md->carryTrim) str += tr(" noTrim");
        if(md->sOffset)  str += tr(" Offset(%1)").arg((double)md->sOffset/256.0f, 0, 'f', 2);
        if(md->curve)
        {
            QString crvStr = CURV_STR;
            str += tr(" Curve(%1)").arg(crvStr.mid(md->curve*3,3).remove(' '));
        }

        if(md->delayDown || md->delayUp) str += tr(" Delay(u%1:d%2)").arg(md->delayUp).arg(md->delayDown);
        if(md->speedDown || md->speedUp) str += tr(" Slow(u%1:d%2)").arg(md->speedUp).arg(md->speedDown);

//        if(md->mixWarn)  str += tr(" Warn(%1)").arg(md->mixWarn);

        if(!mixNotes[i].isEmpty())
            str += " (Note)";

        qba.clear();
        qba.append((quint8)i);
        qba.append((const char*)md, sizeof(MixData));
        QListWidgetItem *itm = new QListWidgetItem(str);
        itm->setData(Qt::UserRole,qba);  // mix number
        MixerlistWidget->addItem(itm);//(str);
        MixerlistWidget->item(MixerlistWidget->count()-1)->setToolTip(mixNotes[i]);
    }

    while(curDest<NUM_XCHNOUT)
    {
        curDest++;
        QString str = getDestStr(curDest);

        qba.clear();
        qba.append((quint8)-curDest);
        QListWidgetItem *itm = new QListWidgetItem(str);
        itm->setData(Qt::UserRole,qba); // add new mixer
        MixerlistWidget->addItem(itm);
    }

    if(MixerlistWidget->selectedItems().isEmpty())
    {
        MixerlistWidget->setCurrentRow(0);
        MixerlistWidget->item(0)->setSelected(true);
    }

}

void ModelEdit::mixesEdited()
{
    updateSettings();
}


void ModelEdit::tabLimits()
{
    for(int i=0; i<NUM_CHNOUT; i++)
    {
        qsbLimitsMin[i] = new QDoubleSpinBox(this);
        qsbLimitsMin[i]->setValue((double)eeData.limitData[i].min/1000.0f);
        qsbLimitsMin[i]->setMaximum(LIMITS_MAX);
        qsbLimitsMin[i]->setMinimum(LIMITS_MIN);
        qsbLimitsMin[i]->setSingleStep(0.1);
        qsbLimitsMin[i]->setAlignment(Qt::AlignRight);
        connect(qsbLimitsMin[i],SIGNAL(editingFinished()),this,SLOT(limitEdited()));
        ui->gridLayout_6->addWidget(qsbLimitsMin[i],i+1,1);

        qsbLimitsMax[i] = new QDoubleSpinBox(this);
        qsbLimitsMax[i]->setValue((double)eeData.limitData[i].max/1000.0f);
        qsbLimitsMax[i]->setMaximum(LIMITS_MAX);
        qsbLimitsMax[i]->setMinimum(LIMITS_MIN);
        qsbLimitsMax[i]->setSingleStep(0.1);
        qsbLimitsMax[i]->setAlignment(Qt::AlignRight);
        connect(qsbLimitsMax[i],SIGNAL(editingFinished()),this,SLOT(limitEdited()));
        ui->gridLayout_6->addWidget(qsbLimitsMax[i],i+1,2);

        qsbLimitsPeriod[i] = new QDoubleSpinBox(this);
        qsbLimitsPeriod[i]->setValue((double)eeData.limitData[i].period/1000.0f);
        qsbLimitsPeriod[i]->setMaximum(LIMITS_MAX);
        qsbLimitsPeriod[i]->setMinimum(LIMITS_MIN);
        qsbLimitsPeriod[i]->setSingleStep(0.1);
        qsbLimitsPeriod[i]->setAlignment(Qt::AlignRight);
        connect(qsbLimitsPeriod[i],SIGNAL(editingFinished()),this,SLOT(limitEdited()));
        ui->gridLayout_6->addWidget(qsbLimitsPeriod[i],i+1,3);

        qsbLimitsInv[i] = new QCheckBox(this);
        qsbLimitsInv[i]->setChecked(eeData.limitData[i].revert);
        connect(qsbLimitsInv[i],SIGNAL(stateChanged(int)),this,SLOT(limitEdited()));
        ui->gridLayout_6->addWidget(qsbLimitsInv[i],i+1,4);
    }
}

void ModelEdit::updateCurvesTab()
{
   ControlCurveSignal(true);
   ui->plotCB_1->setChecked(plot_curve[0]);
   ui->plotCB_2->setChecked(plot_curve[1]);
   ui->plotCB_3->setChecked(plot_curve[2]);
   ui->plotCB_4->setChecked(plot_curve[3]);
   ui->plotCB_5->setChecked(plot_curve[4]);
   ui->plotCB_6->setChecked(plot_curve[5]);
   ui->plotCB_7->setChecked(plot_curve[6]);
   ui->plotCB_8->setChecked(plot_curve[7]);
   ui->plotCB_9->setChecked(plot_curve[8]);
   ui->plotCB_10->setChecked(plot_curve[9]);
   ui->plotCB_11->setChecked(plot_curve[10]);
   ui->plotCB_12->setChecked(plot_curve[11]);
   ui->plotCB_13->setChecked(plot_curve[12]);
   ui->plotCB_14->setChecked(plot_curve[13]);
   ui->plotCB_15->setChecked(plot_curve[14]);
   ui->plotCB_16->setChecked(plot_curve[15]);
   
     ui->curvePt1_1->setValue(eeData.curves5[0][0]);
   ui->curvePt2_1->setValue(eeData.curves5[0][1]);
   ui->curvePt3_1->setValue(eeData.curves5[0][2]);
   ui->curvePt4_1->setValue(eeData.curves5[0][3]);
   ui->curvePt5_1->setValue(eeData.curves5[0][4]);

   ui->curvePt1_2->setValue(eeData.curves5[1][0]);
   ui->curvePt2_2->setValue(eeData.curves5[1][1]);
   ui->curvePt3_2->setValue(eeData.curves5[1][2]);
   ui->curvePt4_2->setValue(eeData.curves5[1][3]);
   ui->curvePt5_2->setValue(eeData.curves5[1][4]);

   ui->curvePt1_3->setValue(eeData.curves5[2][0]);
   ui->curvePt2_3->setValue(eeData.curves5[2][1]);
   ui->curvePt3_3->setValue(eeData.curves5[2][2]);
   ui->curvePt4_3->setValue(eeData.curves5[2][3]);
   ui->curvePt5_3->setValue(eeData.curves5[2][4]);

   ui->curvePt1_4->setValue(eeData.curves5[3][0]);
   ui->curvePt2_4->setValue(eeData.curves5[3][1]);
   ui->curvePt3_4->setValue(eeData.curves5[3][2]);
   ui->curvePt4_4->setValue(eeData.curves5[3][3]);
   ui->curvePt5_4->setValue(eeData.curves5[3][4]);

   ui->curvePt1_5->setValue(eeData.curves5[4][0]);
   ui->curvePt2_5->setValue(eeData.curves5[4][1]);
   ui->curvePt3_5->setValue(eeData.curves5[4][2]);
   ui->curvePt4_5->setValue(eeData.curves5[4][3]);
   ui->curvePt5_5->setValue(eeData.curves5[4][4]);

   ui->curvePt1_6->setValue(eeData.curves5[5][0]);
   ui->curvePt2_6->setValue(eeData.curves5[5][1]);
   ui->curvePt3_6->setValue(eeData.curves5[5][2]);
   ui->curvePt4_6->setValue(eeData.curves5[5][3]);
   ui->curvePt5_6->setValue(eeData.curves5[5][4]);

   ui->curvePt1_7->setValue(eeData.curves5[6][0]);
   ui->curvePt2_7->setValue(eeData.curves5[6][1]);
   ui->curvePt3_7->setValue(eeData.curves5[6][2]);
   ui->curvePt4_7->setValue(eeData.curves5[6][3]);
   ui->curvePt5_7->setValue(eeData.curves5[6][4]);

   ui->curvePt1_8->setValue(eeData.curves5[7][0]);
   ui->curvePt2_8->setValue(eeData.curves5[7][1]);
   ui->curvePt3_8->setValue(eeData.curves5[7][2]);
   ui->curvePt4_8->setValue(eeData.curves5[7][3]);
   ui->curvePt5_8->setValue(eeData.curves5[7][4]);

   ui->curvePt1_9->setValue(eeData.curves9[0][0]);
   ui->curvePt2_9->setValue(eeData.curves9[0][1]);
   ui->curvePt3_9->setValue(eeData.curves9[0][2]);
   ui->curvePt4_9->setValue(eeData.curves9[0][3]);
   ui->curvePt5_9->setValue(eeData.curves9[0][4]);
   ui->curvePt6_9->setValue(eeData.curves9[0][5]);
   ui->curvePt7_9->setValue(eeData.curves9[0][6]);
   ui->curvePt8_9->setValue(eeData.curves9[0][7]);
   ui->curvePt9_9->setValue(eeData.curves9[0][8]);

   ui->curvePt1_10->setValue(eeData.curves9[1][0]);
   ui->curvePt2_10->setValue(eeData.curves9[1][1]);
   ui->curvePt3_10->setValue(eeData.curves9[1][2]);
   ui->curvePt4_10->setValue(eeData.curves9[1][3]);
   ui->curvePt5_10->setValue(eeData.curves9[1][4]);
   ui->curvePt6_10->setValue(eeData.curves9[1][5]);
   ui->curvePt7_10->setValue(eeData.curves9[1][6]);
   ui->curvePt8_10->setValue(eeData.curves9[1][7]);
   ui->curvePt9_10->setValue(eeData.curves9[1][8]);

   ui->curvePt1_11->setValue(eeData.curves9[2][0]);
   ui->curvePt2_11->setValue(eeData.curves9[2][1]);
   ui->curvePt3_11->setValue(eeData.curves9[2][2]);
   ui->curvePt4_11->setValue(eeData.curves9[2][3]);
   ui->curvePt5_11->setValue(eeData.curves9[2][4]);
   ui->curvePt6_11->setValue(eeData.curves9[2][5]);
   ui->curvePt7_11->setValue(eeData.curves9[2][6]);
   ui->curvePt8_11->setValue(eeData.curves9[2][7]);
   ui->curvePt9_11->setValue(eeData.curves9[2][8]);

   ui->curvePt1_12->setValue(eeData.curves9[3][0]);
   ui->curvePt2_12->setValue(eeData.curves9[3][1]);
   ui->curvePt3_12->setValue(eeData.curves9[3][2]);
   ui->curvePt4_12->setValue(eeData.curves9[3][3]);
   ui->curvePt5_12->setValue(eeData.curves9[3][4]);
   ui->curvePt6_12->setValue(eeData.curves9[3][5]);
   ui->curvePt7_12->setValue(eeData.curves9[3][6]);
   ui->curvePt8_12->setValue(eeData.curves9[3][7]);
   ui->curvePt9_12->setValue(eeData.curves9[3][8]);

   ui->curvePt1_13->setValue(eeData.curves9[4][0]);
   ui->curvePt2_13->setValue(eeData.curves9[4][1]);
   ui->curvePt3_13->setValue(eeData.curves9[4][2]);
   ui->curvePt4_13->setValue(eeData.curves9[4][3]);
   ui->curvePt5_13->setValue(eeData.curves9[4][4]);
   ui->curvePt6_13->setValue(eeData.curves9[4][5]);
   ui->curvePt7_13->setValue(eeData.curves9[4][6]);
   ui->curvePt8_13->setValue(eeData.curves9[4][7]);
   ui->curvePt9_13->setValue(eeData.curves9[4][8]);

   ui->curvePt1_14->setValue(eeData.curves9[5][0]);
   ui->curvePt2_14->setValue(eeData.curves9[5][1]);
   ui->curvePt3_14->setValue(eeData.curves9[5][2]);
   ui->curvePt4_14->setValue(eeData.curves9[5][3]);
   ui->curvePt5_14->setValue(eeData.curves9[5][4]);
   ui->curvePt6_14->setValue(eeData.curves9[5][5]);
   ui->curvePt7_14->setValue(eeData.curves9[5][6]);
   ui->curvePt8_14->setValue(eeData.curves9[5][7]);
   ui->curvePt9_14->setValue(eeData.curves9[5][8]);

   ui->curvePt1_15->setValue(eeData.curves9[6][0]);
   ui->curvePt2_15->setValue(eeData.curves9[6][1]);
   ui->curvePt3_15->setValue(eeData.curves9[6][2]);
   ui->curvePt4_15->setValue(eeData.curves9[6][3]);
   ui->curvePt5_15->setValue(eeData.curves9[6][4]);
   ui->curvePt6_15->setValue(eeData.curves9[6][5]);
   ui->curvePt7_15->setValue(eeData.curves9[6][6]);
   ui->curvePt8_15->setValue(eeData.curves9[6][7]);
   ui->curvePt9_15->setValue(eeData.curves9[6][8]);

   ui->curvePt1_16->setValue(eeData.curves9[7][0]);
   ui->curvePt2_16->setValue(eeData.curves9[7][1]);
   ui->curvePt3_16->setValue(eeData.curves9[7][2]);
   ui->curvePt4_16->setValue(eeData.curves9[7][3]);
   ui->curvePt5_16->setValue(eeData.curves9[7][4]);
   ui->curvePt6_16->setValue(eeData.curves9[7][5]);
   ui->curvePt7_16->setValue(eeData.curves9[7][6]);
   ui->curvePt8_16->setValue(eeData.curves9[7][7]);
   ui->curvePt9_16->setValue(eeData.curves9[7][8]);
   ControlCurveSignal(false);
}


void ModelEdit::tabCurves()
{
   for (int i=0; i<16;i++)
	 {
     plot_curve[i]=FALSE;
   }
   updateCurvesTab();

   QGraphicsScene *scene = new QGraphicsScene(ui->curvePreview);
   scene->setItemIndexMethod(QGraphicsScene::NoIndex);
   ui->curvePreview->setScene(scene);
   currentCurve = 0;

   connect(ui->clearMixesPB,SIGNAL(pressed()),this,SLOT(clearCurves()));

   connect(ui->curvePt1_1,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt2_1,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt3_1,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt4_1,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt5_1,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));

   connect(ui->curvePt1_2,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt2_2,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt3_2,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt4_2,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt5_2,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));

   connect(ui->curvePt1_3,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt2_3,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt3_3,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt4_3,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt5_3,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));

   connect(ui->curvePt1_4,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt2_4,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt3_4,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt4_4,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt5_4,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));

   connect(ui->curvePt1_5,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt2_5,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt3_5,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt4_5,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt5_5,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));

   connect(ui->curvePt1_6,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt2_6,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt3_6,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt4_6,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt5_6,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));

   connect(ui->curvePt1_7,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt2_7,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt3_7,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt4_7,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt5_7,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));

   connect(ui->curvePt1_8,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt2_8,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt3_8,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt4_8,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt5_8,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));

   connect(ui->curvePt1_9,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt2_9,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt3_9,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt4_9,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt5_9,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt6_9,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt7_9,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt8_9,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt9_9,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));

   connect(ui->curvePt1_10,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt2_10,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt3_10,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt4_10,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt5_10,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt6_10,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt7_10,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt8_10,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt9_10,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));

   connect(ui->curvePt1_11,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt2_11,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt3_11,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt4_11,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt5_11,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt6_11,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt7_11,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt8_11,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt9_11,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));

   connect(ui->curvePt1_12,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt2_12,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt3_12,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt4_12,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt5_12,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt6_12,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt7_12,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt8_12,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt9_12,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));

   connect(ui->curvePt1_13,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt2_13,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt3_13,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt4_13,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt5_13,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt6_13,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt7_13,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt8_13,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt9_13,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));

   connect(ui->curvePt1_14,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt2_14,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt3_14,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt4_14,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt5_14,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt6_14,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt7_14,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt8_14,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt9_14,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));

   connect(ui->curvePt1_15,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt2_15,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt3_15,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt4_15,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt5_15,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt6_15,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt7_15,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt8_15,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt9_15,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));

   connect(ui->curvePt1_16,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt2_16,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt3_16,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt4_16,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt5_16,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt6_16,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt7_16,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt8_16,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
   connect(ui->curvePt9_16,SIGNAL(valueChanged(int)),this,SLOT(curvePointEdited()));
}

void ModelEdit::setCurrentCurve(int curveId)
{
    currentCurve = curveId;
    QString ss = "QSpinBox { background-color:rgb(255, 255, 127);}";

    QSpinBox* spn[][16] = {
          { ui->curvePt1_1, ui->curvePt2_1, ui->curvePt3_1, ui->curvePt4_1, ui->curvePt5_1 }
        , { ui->curvePt1_2, ui->curvePt2_2, ui->curvePt3_2, ui->curvePt4_2, ui->curvePt5_2 }
        , { ui->curvePt1_3, ui->curvePt2_3, ui->curvePt3_3, ui->curvePt4_3, ui->curvePt5_3 }
        , { ui->curvePt1_4, ui->curvePt2_4, ui->curvePt3_4, ui->curvePt4_4, ui->curvePt5_4 }
        , { ui->curvePt1_5, ui->curvePt2_5, ui->curvePt3_5, ui->curvePt4_5, ui->curvePt5_5 }
        , { ui->curvePt1_6, ui->curvePt2_6, ui->curvePt3_6, ui->curvePt4_6, ui->curvePt5_6 }
        , { ui->curvePt1_7, ui->curvePt2_7, ui->curvePt3_7, ui->curvePt4_7, ui->curvePt5_7 }
        , { ui->curvePt1_8, ui->curvePt2_8, ui->curvePt3_8, ui->curvePt4_8, ui->curvePt5_8 }
        , { ui->curvePt1_9, ui->curvePt2_9, ui->curvePt3_9, ui->curvePt4_9, ui->curvePt5_9, ui->curvePt6_9, ui->curvePt7_9, ui->curvePt8_9, ui->curvePt9_9 }
        , { ui->curvePt1_10, ui->curvePt2_10, ui->curvePt3_10, ui->curvePt4_10, ui->curvePt5_10, ui->curvePt6_10, ui->curvePt7_10, ui->curvePt8_10, ui->curvePt9_10 }
        , { ui->curvePt1_11, ui->curvePt2_11, ui->curvePt3_11, ui->curvePt4_11, ui->curvePt5_11, ui->curvePt6_11, ui->curvePt7_11, ui->curvePt8_11, ui->curvePt9_11 }
        , { ui->curvePt1_12, ui->curvePt2_12, ui->curvePt3_12, ui->curvePt4_12, ui->curvePt5_12, ui->curvePt6_12, ui->curvePt7_12, ui->curvePt8_12, ui->curvePt9_12 }
        , { ui->curvePt1_13, ui->curvePt2_13, ui->curvePt3_13, ui->curvePt4_13, ui->curvePt5_13, ui->curvePt6_13, ui->curvePt7_13, ui->curvePt8_13, ui->curvePt9_13 }
        , { ui->curvePt1_14, ui->curvePt2_14, ui->curvePt3_14, ui->curvePt4_14, ui->curvePt5_14, ui->curvePt6_14, ui->curvePt7_14, ui->curvePt8_14, ui->curvePt9_14 }
        , { ui->curvePt1_15, ui->curvePt2_15, ui->curvePt3_15, ui->curvePt4_15, ui->curvePt5_15, ui->curvePt6_15, ui->curvePt7_15, ui->curvePt8_15, ui->curvePt9_15 }
        , { ui->curvePt1_16, ui->curvePt2_16, ui->curvePt3_16, ui->curvePt4_16, ui->curvePt5_16, ui->curvePt6_16, ui->curvePt7_16, ui->curvePt8_16, ui->curvePt9_16 }
    };
    for (int i = 0; i < 16; i++)
    {
        int jMax = 5;
        if (i > 7) { jMax = 9; }
        for (int j = 0; j < jMax; j++)
        {
            if (curveId == i)
            {
                spn[i][j]->setStyleSheet(ss);
            }
            else
            {
                spn[i][j]->setStyleSheet("");
            }
        }
   }
}

void ModelEdit::curvePointEdited()
{
    
    QSpinBox *spinBox = qobject_cast<QSpinBox*>(sender());

    int curveId = spinBox->objectName().right(1).toInt() - 1;
    if (spinBox->objectName().right(2).left(1).toInt() == 1)
    {
        curveId += 10;
    }

    setCurrentCurve(curveId);

    eeData.curves5[0][0] = ui->curvePt1_1->value();
    eeData.curves5[0][1] = ui->curvePt2_1->value();
    eeData.curves5[0][2] = ui->curvePt3_1->value();
    eeData.curves5[0][3] = ui->curvePt4_1->value();
    eeData.curves5[0][4] = ui->curvePt5_1->value();

    eeData.curves5[1][0] = ui->curvePt1_2->value();
    eeData.curves5[1][1] = ui->curvePt2_2->value();
    eeData.curves5[1][2] = ui->curvePt3_2->value();
    eeData.curves5[1][3] = ui->curvePt4_2->value();
    eeData.curves5[1][4] = ui->curvePt5_2->value();

    eeData.curves5[2][0] = ui->curvePt1_3->value();
    eeData.curves5[2][1] = ui->curvePt2_3->value();
    eeData.curves5[2][2] = ui->curvePt3_3->value();
    eeData.curves5[2][3] = ui->curvePt4_3->value();
    eeData.curves5[2][4] = ui->curvePt5_3->value();

    eeData.curves5[3][0] = ui->curvePt1_4->value();
    eeData.curves5[3][1] = ui->curvePt2_4->value();
    eeData.curves5[3][2] = ui->curvePt3_4->value();
    eeData.curves5[3][3] = ui->curvePt4_4->value();
    eeData.curves5[3][4] = ui->curvePt5_4->value();

    eeData.curves5[4][0] = ui->curvePt1_5->value();
    eeData.curves5[4][1] = ui->curvePt2_5->value();
    eeData.curves5[4][2] = ui->curvePt3_5->value();
    eeData.curves5[4][3] = ui->curvePt4_5->value();
    eeData.curves5[4][4] = ui->curvePt5_5->value();

    eeData.curves5[5][0] = ui->curvePt1_6->value();
    eeData.curves5[5][1] = ui->curvePt2_6->value();
    eeData.curves5[5][2] = ui->curvePt3_6->value();
    eeData.curves5[5][3] = ui->curvePt4_6->value();
    eeData.curves5[5][4] = ui->curvePt5_6->value();

    eeData.curves5[6][0] = ui->curvePt1_7->value();
    eeData.curves5[6][1] = ui->curvePt2_7->value();
    eeData.curves5[6][2] = ui->curvePt3_7->value();
    eeData.curves5[6][3] = ui->curvePt4_7->value();
    eeData.curves5[6][4] = ui->curvePt5_7->value();

    eeData.curves5[7][0] = ui->curvePt1_8->value();
    eeData.curves5[7][1] = ui->curvePt2_8->value();
    eeData.curves5[7][2] = ui->curvePt3_8->value();
    eeData.curves5[7][3] = ui->curvePt4_8->value();
    eeData.curves5[7][4] = ui->curvePt5_8->value();


    eeData.curves9[0][0] = ui->curvePt1_9->value();
    eeData.curves9[0][1] = ui->curvePt2_9->value();
    eeData.curves9[0][2] = ui->curvePt3_9->value();
    eeData.curves9[0][3] = ui->curvePt4_9->value();
    eeData.curves9[0][4] = ui->curvePt5_9->value();
    eeData.curves9[0][5] = ui->curvePt6_9->value();
    eeData.curves9[0][6] = ui->curvePt7_9->value();
    eeData.curves9[0][7] = ui->curvePt8_9->value();
    eeData.curves9[0][8] = ui->curvePt9_9->value();

    eeData.curves9[1][0] = ui->curvePt1_10->value();
    eeData.curves9[1][1] = ui->curvePt2_10->value();
    eeData.curves9[1][2] = ui->curvePt3_10->value();
    eeData.curves9[1][3] = ui->curvePt4_10->value();
    eeData.curves9[1][4] = ui->curvePt5_10->value();
    eeData.curves9[1][5] = ui->curvePt6_10->value();
    eeData.curves9[1][6] = ui->curvePt7_10->value();
    eeData.curves9[1][7] = ui->curvePt8_10->value();
    eeData.curves9[1][8] = ui->curvePt9_10->value();

    eeData.curves9[2][0] = ui->curvePt1_11->value();
    eeData.curves9[2][1] = ui->curvePt2_11->value();
    eeData.curves9[2][2] = ui->curvePt3_11->value();
    eeData.curves9[2][3] = ui->curvePt4_11->value();
    eeData.curves9[2][4] = ui->curvePt5_11->value();
    eeData.curves9[2][5] = ui->curvePt6_11->value();
    eeData.curves9[2][6] = ui->curvePt7_11->value();
    eeData.curves9[2][7] = ui->curvePt8_11->value();
    eeData.curves9[2][8] = ui->curvePt9_11->value();

    eeData.curves9[3][0] = ui->curvePt1_12->value();
    eeData.curves9[3][1] = ui->curvePt2_12->value();
    eeData.curves9[3][2] = ui->curvePt3_12->value();
    eeData.curves9[3][3] = ui->curvePt4_12->value();
    eeData.curves9[3][4] = ui->curvePt5_12->value();
    eeData.curves9[3][5] = ui->curvePt6_12->value();
    eeData.curves9[3][6] = ui->curvePt7_12->value();
    eeData.curves9[3][7] = ui->curvePt8_12->value();
    eeData.curves9[3][8] = ui->curvePt9_12->value();

    eeData.curves9[4][0] = ui->curvePt1_13->value();
    eeData.curves9[4][1] = ui->curvePt2_13->value();
    eeData.curves9[4][2] = ui->curvePt3_13->value();
    eeData.curves9[4][3] = ui->curvePt4_13->value();
    eeData.curves9[4][4] = ui->curvePt5_13->value();
    eeData.curves9[4][5] = ui->curvePt6_13->value();
    eeData.curves9[4][6] = ui->curvePt7_13->value();
    eeData.curves9[4][7] = ui->curvePt8_13->value();
    eeData.curves9[4][8] = ui->curvePt9_13->value();

    eeData.curves9[5][0] = ui->curvePt1_14->value();
    eeData.curves9[5][1] = ui->curvePt2_14->value();
    eeData.curves9[5][2] = ui->curvePt3_14->value();
    eeData.curves9[5][3] = ui->curvePt4_14->value();
    eeData.curves9[5][4] = ui->curvePt5_14->value();
    eeData.curves9[5][5] = ui->curvePt6_14->value();
    eeData.curves9[5][6] = ui->curvePt7_14->value();
    eeData.curves9[5][7] = ui->curvePt8_14->value();
    eeData.curves9[5][8] = ui->curvePt9_14->value();

    eeData.curves9[6][0] = ui->curvePt1_15->value();
    eeData.curves9[6][1] = ui->curvePt2_15->value();
    eeData.curves9[6][2] = ui->curvePt3_15->value();
    eeData.curves9[6][3] = ui->curvePt4_15->value();
    eeData.curves9[6][4] = ui->curvePt5_15->value();
    eeData.curves9[6][5] = ui->curvePt6_15->value();
    eeData.curves9[6][6] = ui->curvePt7_15->value();
    eeData.curves9[6][7] = ui->curvePt8_15->value();
    eeData.curves9[6][8] = ui->curvePt9_15->value();

    eeData.curves9[7][0] = ui->curvePt1_16->value();
    eeData.curves9[7][1] = ui->curvePt2_16->value();
    eeData.curves9[7][2] = ui->curvePt3_16->value();
    eeData.curves9[7][3] = ui->curvePt4_16->value();
    eeData.curves9[7][4] = ui->curvePt5_16->value();
    eeData.curves9[7][5] = ui->curvePt6_16->value();
    eeData.curves9[7][6] = ui->curvePt7_16->value();
    eeData.curves9[7][7] = ui->curvePt8_16->value();
    eeData.curves9[7][8] = ui->curvePt9_16->value();

    if (redrawCurve)
    {
        drawCurve();
    }
    updateSettings();
}


void ModelEdit::setSwitchWidgetVisibility(int i)
{
    switch CS_STATE(eeData.customSw[i].func)
    {
    case CS_VOFS:
        cswitchSource1[i]->setVisible(true);
        cswitchSource2[i]->setVisible(false);
        cswitchOffset[i]->setVisible(true);
        populateSourceCB(cswitchSource1[i],eeData.customSw[i].v1);
        cswitchOffset[i]->setValue(eeData.customSw[i].v2);
        break;
    case CS_VBOOL:
        cswitchSource1[i]->setVisible(true);
        cswitchSource2[i]->setVisible(true);
        cswitchOffset[i]->setVisible(false);
        populateSwitchCB(cswitchSource1[i],eeData.customSw[i].v1);
        populateSwitchCB(cswitchSource2[i],eeData.customSw[i].v2);
        break;
    case CS_VCOMP:
        cswitchSource1[i]->setVisible(true);
        cswitchSource2[i]->setVisible(true);
        cswitchOffset[i]->setVisible(false);
        populateSourceCB(cswitchSource1[i],eeData.customSw[i].v1);
        populateSourceCB(cswitchSource2[i],eeData.customSw[i].v2);
        break;
    default:
        break;
    }
}

void ModelEdit::updateSwitchesTab()
{
    switchEditLock = true;

    populateCSWCB(ui->cswitchFunc_1, eeData.customSw[0].func);
    populateCSWCB(ui->cswitchFunc_2, eeData.customSw[1].func);
    populateCSWCB(ui->cswitchFunc_3, eeData.customSw[2].func);
    populateCSWCB(ui->cswitchFunc_4, eeData.customSw[3].func);
    populateCSWCB(ui->cswitchFunc_5, eeData.customSw[4].func);
    populateCSWCB(ui->cswitchFunc_6, eeData.customSw[5].func);
    populateCSWCB(ui->cswitchFunc_7, eeData.customSw[6].func);
    populateCSWCB(ui->cswitchFunc_8, eeData.customSw[7].func);
    populateCSWCB(ui->cswitchFunc_9, eeData.customSw[8].func);
    populateCSWCB(ui->cswitchFunc_10,eeData.customSw[9].func);
    populateCSWCB(ui->cswitchFunc_11,eeData.customSw[10].func);
    populateCSWCB(ui->cswitchFunc_12,eeData.customSw[11].func);

    for(int i=0; i<NUM_SWITCHES; i++)
        setSwitchWidgetVisibility(i);

    switchEditLock = false;
}

void ModelEdit::tabSwitches()
{
    switchEditLock = true;

    for(int i=0; i<NUM_SWITCHES; i++)
    {
        cswitchSource1[i] = new QComboBox(this);
        connect(cswitchSource1[i],SIGNAL(currentIndexChanged(int)),this,SLOT(switchesEdited()));
        ui->gridLayout_8->addWidget(cswitchSource1[i],i+1,2);
        cswitchSource1[i]->setVisible(false);

        cswitchSource2[i] = new QComboBox(this);
        connect(cswitchSource2[i],SIGNAL(currentIndexChanged(int)),this,SLOT(switchesEdited()));
        ui->gridLayout_8->addWidget(cswitchSource2[i],i+1,3);
        cswitchSource2[i]->setVisible(false);

        cswitchOffset[i] = new QSpinBox(this);
        cswitchOffset[i]->setMaximum(125);
        cswitchOffset[i]->setMinimum(-125);
        cswitchOffset[i]->setAccelerated(true);
        connect(cswitchOffset[i],SIGNAL(editingFinished()),this,SLOT(switchesEdited()));
        ui->gridLayout_8->addWidget(cswitchOffset[i],i+1,3);
        cswitchOffset[i]->setVisible(false);
    }

    updateSwitchesTab();

    //connects
    connect(ui->cswitchFunc_1,SIGNAL(currentIndexChanged(int)),this,SLOT(switchesEdited()));
    connect(ui->cswitchFunc_2,SIGNAL(currentIndexChanged(int)),this,SLOT(switchesEdited()));
    connect(ui->cswitchFunc_3,SIGNAL(currentIndexChanged(int)),this,SLOT(switchesEdited()));
    connect(ui->cswitchFunc_4,SIGNAL(currentIndexChanged(int)),this,SLOT(switchesEdited()));
    connect(ui->cswitchFunc_5,SIGNAL(currentIndexChanged(int)),this,SLOT(switchesEdited()));
    connect(ui->cswitchFunc_6,SIGNAL(currentIndexChanged(int)),this,SLOT(switchesEdited()));
    connect(ui->cswitchFunc_7,SIGNAL(currentIndexChanged(int)),this,SLOT(switchesEdited()));
    connect(ui->cswitchFunc_8,SIGNAL(currentIndexChanged(int)),this,SLOT(switchesEdited()));
    connect(ui->cswitchFunc_9,SIGNAL(currentIndexChanged(int)),this,SLOT(switchesEdited()));
    connect(ui->cswitchFunc_10,SIGNAL(currentIndexChanged(int)),this,SLOT(switchesEdited()));
    connect(ui->cswitchFunc_11,SIGNAL(currentIndexChanged(int)),this,SLOT(switchesEdited()));
    connect(ui->cswitchFunc_12,SIGNAL(currentIndexChanged(int)),this,SLOT(switchesEdited()));

    switchEditLock = false;
}

void ModelEdit::tabSafetySwitches()
{
    for(int i=0; i<NUM_CHNOUT; i++)
    {
        safetySwitchSwtch[i] = new QComboBox(this);
        populateSwitchCB(safetySwitchSwtch[i],eeData.safetySw[i].swtch);
        ui->grid_tabSafetySwitches->addWidget(safetySwitchSwtch[i],i+1,1);
        connect(safetySwitchSwtch[i],SIGNAL(currentIndexChanged(int)),this,SLOT(safetySwitchesEdited()));

        safetySwitchValue[i] = new QSpinBox(this);
        safetySwitchValue[i]->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
        safetySwitchValue[i]->setMaximum(125);
        safetySwitchValue[i]->setMinimum(-125);
        safetySwitchValue[i]->setAccelerated(true);
        safetySwitchValue[i]->setValue(eeData.safetySw[i].val);
        ui->grid_tabSafetySwitches->addWidget(safetySwitchValue[i],i+1,2);
        connect(safetySwitchValue[i],SIGNAL(editingFinished()),this,SLOT(safetySwitchesEdited()));
    }
}

void ModelEdit::switchesEdited()
{
    if(switchEditLock) return;
    switchEditLock = true;

    bool chAr[NUM_SWITCHES];

    chAr[0]  = (CS_STATE(eeData.customSw[0].func)) !=(CS_STATE(ui->cswitchFunc_1->currentIndex()));
    chAr[1]  = (CS_STATE(eeData.customSw[1].func)) !=(CS_STATE(ui->cswitchFunc_2->currentIndex()));
    chAr[2]  = (CS_STATE(eeData.customSw[2].func)) !=(CS_STATE(ui->cswitchFunc_3->currentIndex()));
    chAr[3]  = (CS_STATE(eeData.customSw[3].func)) !=(CS_STATE(ui->cswitchFunc_4->currentIndex()));
    chAr[4]  = (CS_STATE(eeData.customSw[4].func)) !=(CS_STATE(ui->cswitchFunc_5->currentIndex()));
    chAr[5]  = (CS_STATE(eeData.customSw[5].func)) !=(CS_STATE(ui->cswitchFunc_6->currentIndex()));
    chAr[6]  = (CS_STATE(eeData.customSw[6].func)) !=(CS_STATE(ui->cswitchFunc_7->currentIndex()));
    chAr[7]  = (CS_STATE(eeData.customSw[7].func)) !=(CS_STATE(ui->cswitchFunc_8->currentIndex()));
    chAr[8]  = (CS_STATE(eeData.customSw[8].func)) !=(CS_STATE(ui->cswitchFunc_9->currentIndex()));
    chAr[9]  = (CS_STATE(eeData.customSw[9].func)) !=(CS_STATE(ui->cswitchFunc_10->currentIndex()));
    chAr[10] = (CS_STATE(eeData.customSw[10].func))!=(CS_STATE(ui->cswitchFunc_11->currentIndex()));
    chAr[11] = (CS_STATE(eeData.customSw[11].func))!=(CS_STATE(ui->cswitchFunc_12->currentIndex()));

    eeData.customSw[0].func  = ui->cswitchFunc_1->currentIndex();
    eeData.customSw[1].func  = ui->cswitchFunc_2->currentIndex();
    eeData.customSw[2].func  = ui->cswitchFunc_3->currentIndex();
    eeData.customSw[3].func  = ui->cswitchFunc_4->currentIndex();
    eeData.customSw[4].func  = ui->cswitchFunc_5->currentIndex();
    eeData.customSw[5].func  = ui->cswitchFunc_6->currentIndex();
    eeData.customSw[6].func  = ui->cswitchFunc_7->currentIndex();
    eeData.customSw[7].func  = ui->cswitchFunc_8->currentIndex();
    eeData.customSw[8].func  = ui->cswitchFunc_9->currentIndex();
    eeData.customSw[9].func  = ui->cswitchFunc_10->currentIndex();
    eeData.customSw[10].func = ui->cswitchFunc_11->currentIndex();
    eeData.customSw[11].func = ui->cswitchFunc_12->currentIndex();


    for(int i=0; i<NUM_SWITCHES; i++)
    {
        if(chAr[i])
        {
            eeData.customSw[i].v1 = 0;
            eeData.customSw[i].v2 = 0;
            setSwitchWidgetVisibility(i);
        }

        switch(CS_STATE(eeData.customSw[i].func))
        {
        case (CS_VOFS):
            eeData.customSw[i].v1 = cswitchSource1[i]->currentIndex();
            eeData.customSw[i].v2 = cswitchOffset[i]->value();
            break;
        case (CS_VBOOL):
            eeData.customSw[i].v1 = cswitchSource1[i]->currentIndex() - NUM_SWITCHES-1;
            eeData.customSw[i].v2 = cswitchSource2[i]->currentIndex() - NUM_SWITCHES-1;
            break;
        case (CS_VCOMP):
            eeData.customSw[i].v1 = cswitchSource1[i]->currentIndex();
            eeData.customSw[i].v2 = cswitchSource2[i]->currentIndex();
            break;
        default:
            break;
        }
    }

    updateSettings();

    switchEditLock = false;
}



QSpinBox *ModelEdit::getNodeSB(int i)   // get the SpinBox that corresponds to the selected node
{
    if(currentCurve==0 && i==0) return ui->curvePt1_1;
    if(currentCurve==0 && i==1) return ui->curvePt2_1;
    if(currentCurve==0 && i==2) return ui->curvePt3_1;
    if(currentCurve==0 && i==3) return ui->curvePt4_1;
    if(currentCurve==0 && i==4) return ui->curvePt5_1;

    if(currentCurve==1 && i==0) return ui->curvePt1_2;
    if(currentCurve==1 && i==1) return ui->curvePt2_2;
    if(currentCurve==1 && i==2) return ui->curvePt3_2;
    if(currentCurve==1 && i==3) return ui->curvePt4_2;
    if(currentCurve==1 && i==4) return ui->curvePt5_2;

    if(currentCurve==2 && i==0) return ui->curvePt1_3;
    if(currentCurve==2 && i==1) return ui->curvePt2_3;
    if(currentCurve==2 && i==2) return ui->curvePt3_3;
    if(currentCurve==2 && i==3) return ui->curvePt4_3;
    if(currentCurve==2 && i==4) return ui->curvePt5_3;

    if(currentCurve==3 && i==0) return ui->curvePt1_4;
    if(currentCurve==3 && i==1) return ui->curvePt2_4;
    if(currentCurve==3 && i==2) return ui->curvePt3_4;
    if(currentCurve==3 && i==3) return ui->curvePt4_4;
    if(currentCurve==3 && i==4) return ui->curvePt5_4;

    if(currentCurve==4 && i==0) return ui->curvePt1_5;
    if(currentCurve==4 && i==1) return ui->curvePt2_5;
    if(currentCurve==4 && i==2) return ui->curvePt3_5;
    if(currentCurve==4 && i==3) return ui->curvePt4_5;
    if(currentCurve==4 && i==4) return ui->curvePt5_5;

    if(currentCurve==5 && i==0) return ui->curvePt1_6;
    if(currentCurve==5 && i==1) return ui->curvePt2_6;
    if(currentCurve==5 && i==2) return ui->curvePt3_6;
    if(currentCurve==5 && i==3) return ui->curvePt4_6;
    if(currentCurve==5 && i==4) return ui->curvePt5_6;

    if(currentCurve==6 && i==0) return ui->curvePt1_7;
    if(currentCurve==6 && i==1) return ui->curvePt2_7;
    if(currentCurve==6 && i==2) return ui->curvePt3_7;
    if(currentCurve==6 && i==3) return ui->curvePt4_7;
    if(currentCurve==6 && i==4) return ui->curvePt5_7;

    if(currentCurve==7 && i==0) return ui->curvePt1_8;
    if(currentCurve==7 && i==1) return ui->curvePt2_8;
    if(currentCurve==7 && i==2) return ui->curvePt3_8;
    if(currentCurve==7 && i==3) return ui->curvePt4_8;
    if(currentCurve==7 && i==4) return ui->curvePt5_8;


    if(currentCurve==8 && i==0) return ui->curvePt1_9;
    if(currentCurve==8 && i==1) return ui->curvePt2_9;
    if(currentCurve==8 && i==2) return ui->curvePt3_9;
    if(currentCurve==8 && i==3) return ui->curvePt4_9;
    if(currentCurve==8 && i==4) return ui->curvePt5_9;
    if(currentCurve==8 && i==5) return ui->curvePt6_9;
    if(currentCurve==8 && i==6) return ui->curvePt7_9;
    if(currentCurve==8 && i==7) return ui->curvePt8_9;
    if(currentCurve==8 && i==8) return ui->curvePt9_9;

    if(currentCurve==9 && i==0) return ui->curvePt1_10;
    if(currentCurve==9 && i==1) return ui->curvePt2_10;
    if(currentCurve==9 && i==2) return ui->curvePt3_10;
    if(currentCurve==9 && i==3) return ui->curvePt4_10;
    if(currentCurve==9 && i==4) return ui->curvePt5_10;
    if(currentCurve==9 && i==5) return ui->curvePt6_10;
    if(currentCurve==9 && i==6) return ui->curvePt7_10;
    if(currentCurve==9 && i==7) return ui->curvePt8_10;
    if(currentCurve==9 && i==8) return ui->curvePt9_10;

    if(currentCurve==10 && i==0) return ui->curvePt1_11;
    if(currentCurve==10 && i==1) return ui->curvePt2_11;
    if(currentCurve==10 && i==2) return ui->curvePt3_11;
    if(currentCurve==10 && i==3) return ui->curvePt4_11;
    if(currentCurve==10 && i==4) return ui->curvePt5_11;
    if(currentCurve==10 && i==5) return ui->curvePt6_11;
    if(currentCurve==10 && i==6) return ui->curvePt7_11;
    if(currentCurve==10 && i==7) return ui->curvePt8_11;
    if(currentCurve==10 && i==8) return ui->curvePt9_11;

    if(currentCurve==11 && i==0) return ui->curvePt1_12;
    if(currentCurve==11 && i==1) return ui->curvePt2_12;
    if(currentCurve==11 && i==2) return ui->curvePt3_12;
    if(currentCurve==11 && i==3) return ui->curvePt4_12;
    if(currentCurve==11 && i==4) return ui->curvePt5_12;
    if(currentCurve==11 && i==5) return ui->curvePt6_12;
    if(currentCurve==11 && i==6) return ui->curvePt7_12;
    if(currentCurve==11 && i==7) return ui->curvePt8_12;
    if(currentCurve==11 && i==8) return ui->curvePt9_12;

    if(currentCurve==12 && i==0) return ui->curvePt1_13;
    if(currentCurve==12 && i==1) return ui->curvePt2_13;
    if(currentCurve==12 && i==2) return ui->curvePt3_13;
    if(currentCurve==12 && i==3) return ui->curvePt4_13;
    if(currentCurve==12 && i==4) return ui->curvePt5_13;
    if(currentCurve==12 && i==5) return ui->curvePt6_13;
    if(currentCurve==12 && i==6) return ui->curvePt7_13;
    if(currentCurve==12 && i==7) return ui->curvePt8_13;
    if(currentCurve==12 && i==8) return ui->curvePt9_13;

    if(currentCurve==13 && i==0) return ui->curvePt1_14;
    if(currentCurve==13 && i==1) return ui->curvePt2_14;
    if(currentCurve==13 && i==2) return ui->curvePt3_14;
    if(currentCurve==13 && i==3) return ui->curvePt4_14;
    if(currentCurve==13 && i==4) return ui->curvePt5_14;
    if(currentCurve==13 && i==5) return ui->curvePt6_14;
    if(currentCurve==13 && i==6) return ui->curvePt7_14;
    if(currentCurve==13 && i==7) return ui->curvePt8_14;
    if(currentCurve==13 && i==8) return ui->curvePt9_14;

    if(currentCurve==14 && i==0) return ui->curvePt1_15;
    if(currentCurve==14 && i==1) return ui->curvePt2_15;
    if(currentCurve==14 && i==2) return ui->curvePt3_15;
    if(currentCurve==14 && i==3) return ui->curvePt4_15;
    if(currentCurve==14 && i==4) return ui->curvePt5_15;
    if(currentCurve==14 && i==5) return ui->curvePt6_15;
    if(currentCurve==14 && i==6) return ui->curvePt7_15;
    if(currentCurve==14 && i==7) return ui->curvePt8_15;
    if(currentCurve==14 && i==8) return ui->curvePt9_15;

    if(currentCurve==15 && i==0) return ui->curvePt1_16;
    if(currentCurve==15 && i==1) return ui->curvePt2_16;
    if(currentCurve==15 && i==2) return ui->curvePt3_16;
    if(currentCurve==15 && i==3) return ui->curvePt4_16;
    if(currentCurve==15 && i==4) return ui->curvePt5_16;
    if(currentCurve==15 && i==5) return ui->curvePt6_16;
    if(currentCurve==15 && i==6) return ui->curvePt7_16;
    if(currentCurve==15 && i==7) return ui->curvePt8_16;
    if(currentCurve==15 && i==8) return ui->curvePt9_16;

    return 0;
}

void ModelEdit::drawCurve()
{
    int k,i;
    QColor * plot_color[16];
    plot_color[0]=new QColor(0,0,127);
    plot_color[1]=new QColor(0,127,0);
    plot_color[2]=new QColor(127,0,0);
    plot_color[3]=new QColor(0,127,127);
    plot_color[4]=new QColor(127,0,127);
    plot_color[5]=new QColor(127,127,0);
    plot_color[6]=new QColor(127,127,127);
    plot_color[7]=new QColor(0,0,255);
    plot_color[8]=new QColor(0,127,255);
    plot_color[9]=new QColor(127,0,255);
    plot_color[10]=new QColor(0,255,0);
    plot_color[11]=new QColor(0,255,127);
    plot_color[12]=new QColor(127,255,0);
    plot_color[13]=new QColor(255,0,0);
    plot_color[14]=new QColor(255,0,127);
    plot_color[15]=new QColor(255,127,0);
    
		if(currentCurve<0 || currentCurve>15) return;

    Node *nodel = 0;
    Node *nodex = 0;

    QGraphicsScene *scene = ui->curvePreview->scene();
    QPen pen;
    QColor color;
    scene->clear();

    qreal width  = scene->sceneRect().width();
    qreal height = scene->sceneRect().height();

    qreal centerX = scene->sceneRect().left() + width/2; //center X
    qreal centerY = scene->sceneRect().top() + height/2; //center Y

    QGraphicsSimpleTextItem *ti;
    ti = scene->addSimpleText(tr("Editing curve %1").arg(currentCurve+1));
    ti->setPos(3,3);

    scene->addLine(centerX,GFX_MARGIN,centerX,height+GFX_MARGIN);
    scene->addLine(GFX_MARGIN,centerY,width+GFX_MARGIN,centerY);

    pen.setWidth(2);
    pen.setStyle(Qt::SolidLine);
    for(k=0; k<8; k++) {
        pen.setColor(*plot_color[k]);
        if ((currentCurve!=k) && (plot_curve[k])) {
           for(i=0; i<4; i++) {
                scene->addLine(GFX_MARGIN + i*width/(5-1),centerY - (qreal)eeData.curves5[k][i]*height/200,GFX_MARGIN + (i+1)*width/(5-1),centerY - (qreal)eeData.curves5[k][i+1]*height/200,pen);
           }
        }
    }
    for(k=0; k<8; k++) {
        pen.setColor(*plot_color[k+8]);
        if ((currentCurve!=(k+8)) && (plot_curve[k+8])) {
           for(i=0; i<8; i++) {
                scene->addLine(GFX_MARGIN + i*width/(9-1),centerY - (qreal)eeData.curves9[k][i]*height/200,GFX_MARGIN + (i+1)*width/(9-1),centerY - (qreal)eeData.curves9[k][i+1]*height/200,pen);
           }
        }
    }

    if(currentCurve<8)
        for(i=0; i<5; i++)
        {
            nodel = nodex;
            nodex = new Node(getNodeSB(i));
            nodex->setFixedX(true);

            nodex->setPos(GFX_MARGIN + i*width/(5-1),centerY - (qreal)eeData.curves5[currentCurve][i]*height/200);
            scene->addItem(nodex);
            if(i>0) scene->addItem(new Edge(nodel, nodex));
        }
    else
        for(i=0; i<9; i++)
        {
            nodel = nodex;
            nodex = new Node(getNodeSB(i));
            nodex->setFixedX(true);

            nodex->setPos(GFX_MARGIN + i*width/(9-1),centerY - (qreal)eeData.curves9[currentCurve-8][i]*height/200);
            scene->addItem(nodex);
            if(i>0) scene->addItem(new Edge(nodel, nodex));
        }
}



void ModelEdit::on_curveEdit_1_clicked()
{
    setCurrentCurve(0);
    drawCurve();
}

void ModelEdit::on_curveEdit_2_clicked()
{
    setCurrentCurve(1);
    drawCurve();
}

void ModelEdit::on_curveEdit_3_clicked()
{
    setCurrentCurve(2);
    drawCurve();
}

void ModelEdit::on_curveEdit_4_clicked()
{
    setCurrentCurve(3);
    drawCurve();
}

void ModelEdit::on_curveEdit_5_clicked()
{
    setCurrentCurve(4);
    drawCurve();
}

void ModelEdit::on_curveEdit_6_clicked()
{
    setCurrentCurve(5);
    drawCurve();
}

void ModelEdit::on_curveEdit_7_clicked()
{
    setCurrentCurve(6);
    drawCurve();
}

void ModelEdit::on_curveEdit_8_clicked()
{
    setCurrentCurve(7);
    drawCurve();
}

void ModelEdit::on_curveEdit_9_clicked()
{
    setCurrentCurve(8);
    drawCurve();
}

void ModelEdit::on_curveEdit_10_clicked()
{
    setCurrentCurve(9);
    drawCurve();
}

void ModelEdit::on_curveEdit_11_clicked()
{
    setCurrentCurve(10);
    drawCurve();
}

void ModelEdit::on_curveEdit_12_clicked()
{
    setCurrentCurve(11);
    drawCurve();
}

void ModelEdit::on_curveEdit_13_clicked()
{
    setCurrentCurve(12);
    drawCurve();
}

void ModelEdit::on_curveEdit_14_clicked()
{
    setCurrentCurve(13);
    drawCurve();
}

void ModelEdit::on_curveEdit_15_clicked()
{
    setCurrentCurve(14);
    drawCurve();
}

void ModelEdit::on_curveEdit_16_clicked()
{
    setCurrentCurve(15);
    drawCurve();
}


bool ModelEdit::gm_insertMix(int idx)
{
    if(idx<0 || idx>=MAX_MIXERS) return false;
    if(eeData.mixData[MAX_MIXERS-1].destCh) return false; //if last mixer isn't empty - can't add more

    int i = eeData.mixData[idx].destCh;
    memmove(&eeData.mixData[idx+1],&eeData.mixData[idx],
            (MAX_MIXERS-(idx+1))*sizeof(MixData) );
    memset(&eeData.mixData[idx],0,sizeof(MixData));
    eeData.mixData[idx].destCh = i;
    eeData.mixData[idx].weight = 0;

    for(int j=(MAX_MIXERS-1); j>idx; j--)
    {
        mixNotes[j].clear();
        mixNotes[j].append(mixNotes[j-1]);
    }
    mixNotes[idx].clear();

    return true;
}

void ModelEdit::gm_deleteMix(int index)
{
  memmove(&eeData.mixData[index],&eeData.mixData[index+1],
            (MAX_MIXERS-(index+1))*sizeof(MixData));
  memset(&eeData.mixData[MAX_MIXERS-1],0,sizeof(MixData));

  for(int j=index; j<(MAX_MIXERS-1); j++)
  {
      mixNotes[j].clear();
      mixNotes[j].append(mixNotes[j+1]);
  }
  mixNotes[MAX_MIXERS-1].clear();
}

void ModelEdit::gm_openMix(int index)
{
    if(index<0 || index>=MAX_MIXERS) return;

    MixData mixd;
    memcpy(&mixd,&eeData.mixData[index],sizeof(MixData));

    updateSettings();
    tabMixes();

    QString comment = mixNotes[index];

    MixerDialog *g = new MixerDialog(this,&mixd, &comment);
    if(g->exec())
    {
        memcpy(&eeData.mixData[index],&mixd,sizeof(MixData));

        mixNotes[index] = comment;

        updateSettings();
        tabMixes();
    }
}

int ModelEdit::getMixerIndex(int dch)
{
    int i = 0;
    while ((eeData.mixData[i].destCh<=dch) && (eeData.mixData[i].destCh) && (i<MAX_MIXERS)) i++;
    if(i==MAX_MIXERS) return -1;
    return i;
}

void ModelEdit::mixerlistWidget_doubleClicked(QModelIndex index)
{
    int idx= MixerlistWidget->item(index.row())->data(Qt::UserRole).toByteArray().at(0);
    if(idx<0)
    {
        int i = -idx;
        idx = getMixerIndex(i); //get mixer index to insert
        if(!gm_insertMix(idx))
            return; //if full - don't add any more mixes
        eeData.mixData[idx].destCh = i;
    }
    gm_openMix(idx);
}

void ModelEdit::mixersDeleteList(QList<int> list)
{
    qSort(list.begin(), list.end());

    int iDec = 0;
    foreach(int idx, list)
    {
        gm_deleteMix(idx-iDec);
        iDec++;
    }
}

QList<int> ModelEdit::createListFromSelected()
{
    QList<int> list;
    foreach(QListWidgetItem *item, MixerlistWidget->selectedItems())
    {
        int idx= item->data(Qt::UserRole).toByteArray().at(0);
        if(idx>=0 && idx<MAX_MIXERS) list << idx;
    }
    return list;
}


void ModelEdit::setSelectedByList(QList<int> list)
{
    for(int i=0; i<MixerlistWidget->count(); i++)
    {
        int t = MixerlistWidget->item(i)->data(Qt::UserRole).toByteArray().at(0);
        if(list.contains(t))
            MixerlistWidget->item(i)->setSelected(true);
    }
}

void ModelEdit::mixersDelete(bool ask)
{
    int curpos = MixerlistWidget->currentRow();

    QMessageBox::StandardButton ret = QMessageBox::No;

    if(ask)
        ret = QMessageBox::warning(this, "pipo",
                 tr("Delete Selected Mixes?"),
                 QMessageBox::Yes | QMessageBox::No);


    if ((ret == QMessageBox::Yes) || (!ask))
    {
        mixersDeleteList(createListFromSelected());
        updateSettings();
        tabMixes();

        MixerlistWidget->setCurrentRow(curpos);
    }
}

void ModelEdit::mixersCut()
{
    mixersCopy();
    mixersDelete(false);
}

void ModelEdit::mixersCopy()
{
    QList<int> list = createListFromSelected();

    QByteArray mxData;
    foreach(int idx, list)
        mxData.append((char*)&eeData.mixData[idx],sizeof(MixData));

    QMimeData *mimeData = new QMimeData;
    mimeData->setData("application/x-pipo-mix", mxData);

    QApplication::clipboard()->setMimeData(mimeData,QClipboard::Clipboard);
}

void ModelEdit::mimeDropped(int index, const QMimeData *data, Qt::DropAction action)
{
    int idx= MixerlistWidget->item(index)->data(Qt::UserRole).toByteArray().at(0);
    pasteMIMEData(data,idx);
    if(action) {}
}

void ModelEdit::pasteMIMEData(const QMimeData * mimeData, int destIdx)
{
    int curpos = MixerlistWidget->currentRow();

    if(mimeData->hasFormat("application/x-pipo-mix"))
    {
        int idx = MixerlistWidget->currentItem()->data(Qt::UserRole).toByteArray().at(0);
        if(destIdx!=1000)
            idx = destIdx>=0 ? destIdx-1 : destIdx;


        int dch = -idx;
        if(idx<0)
            idx = getMixerIndex(-idx) - 1; //get mixer index to insert
        else
            dch = eeData.mixData[idx].destCh;

        QByteArray mxData = mimeData->data("application/x-pipo-mix");

        int i = 0;
        while(i<mxData.size())
        {
            idx++;
            if(idx==MAX_MIXERS) break;

            if(!gm_insertMix(idx))
                break; //memory full - can't add any more
            MixData *md = &eeData.mixData[idx];
            memcpy(md,mxData.mid(i,sizeof(MixData)).constData(),sizeof(MixData));
            md->destCh = dch;

            i     += sizeof(MixData);
        }

        updateSettings();
        tabMixes();

        MixerlistWidget->setCurrentRow(curpos);
    }
}

void ModelEdit::mixersPaste()
{
    const QClipboard *clipboard = QApplication::clipboard();
    const QMimeData *mimeData = clipboard->mimeData();

    pasteMIMEData(mimeData);
}

void ModelEdit::mixersDuplicate()
{
    mixersCopy();
    mixersPaste();
}

void ModelEdit::mixerOpen()
{
    int idx = MixerlistWidget->currentItem()->data(Qt::UserRole).toByteArray().at(0);
    if(idx<0)
    {
        int i = -idx;
        idx = getMixerIndex(i); //get mixer index to insert
        if(!gm_insertMix(idx))
            return;
        eeData.mixData[idx].destCh = i;
    }
    gm_openMix(idx);
}

void ModelEdit::setNote(int i, QString s)
{
    if(!s.isEmpty())
    {
        mixNotes[i].clear();
        mixNotes[i].append(s);
    }
}

void ModelEdit::mixerAdd()
{
    int index = MixerlistWidget->currentItem()->data(Qt::UserRole).toByteArray().at(0);

    if(index<0)  // if empty then return relavent index
    {
        int i = -index;
        index = getMixerIndex(i); //get mixer index to insert
        if(!gm_insertMix(index))
            return;
        eeData.mixData[index].destCh = i;
    }
    else
    {
        index++;
        if(!gm_insertMix(index))
            return;
        eeData.mixData[index].destCh = eeData.mixData[index-1].destCh;
    }

    gm_openMix(index);

}

void ModelEdit::mixerlistWidget_customContextMenuRequested(QPoint pos)
{
    QPoint globalPos = MixerlistWidget->mapToGlobal(pos);

    const QClipboard *clipboard = QApplication::clipboard();
    const QMimeData *mimeData = clipboard->mimeData();
    bool hasData = mimeData->hasFormat("application/x-pipo-mix");

    QMenu contextMenu;
    contextMenu.addAction(QIcon(":/images/add.png"), tr("&Add"),this,SLOT(mixerAdd()),tr("Ctrl+A"));
    contextMenu.addAction(QIcon(":/images/edit.png"), tr("&Edit"),this,SLOT(mixerOpen()),tr("Enter"));
    contextMenu.addSeparator();
    contextMenu.addAction(QIcon(":/images/clear.png"), tr("&Delete"),this,SLOT(mixersDelete()),tr("Delete"));
    contextMenu.addAction(QIcon(":/images/copy.png"), tr("&Copy"),this,SLOT(mixersCopy()),tr("Ctrl+C"));
    contextMenu.addAction(QIcon(":/images/cut.png"), tr("&Cut"),this,SLOT(mixersCut()),tr("Ctrl+X"));
    contextMenu.addAction(QIcon(":/images/paste.png"), tr("&Paste"),this,SLOT(mixersPaste()),tr("Ctrl+V"))->setEnabled(hasData);
    contextMenu.addAction(QIcon(":/images/duplicate.png"), tr("Du&plicate"),this,SLOT(mixersDuplicate()),tr("Ctrl+U"));
    contextMenu.addSeparator();
    contextMenu.addAction(QIcon(":/images/moveup.png"), tr("Move Up"),this,SLOT(moveMixUp()),tr("Ctrl+Up"));
    contextMenu.addAction(QIcon(":/images/movedown.png"), tr("Move Down"),this,SLOT(moveMixDown()),tr("Ctrl+Down"));

    contextMenu.exec(globalPos);
}

void ModelEdit::mixerlistWidget_KeyPress(QKeyEvent *event)
{
    if(event->matches(QKeySequence::SelectAll)) mixerAdd();  //Ctrl A
    if(event->matches(QKeySequence::Delete))    mixersDelete();
    if(event->matches(QKeySequence::Copy))      mixersCopy();
    if(event->matches(QKeySequence::Cut))       mixersCut();
    if(event->matches(QKeySequence::Paste))     mixersPaste();
    if(event->matches(QKeySequence::Underline)) mixersDuplicate();

    if(event->key()==Qt::Key_Return || event->key()==Qt::Key_Enter) mixerOpen();
    if(event->matches(QKeySequence::MoveToNextLine))
        MixerlistWidget->setCurrentRow(MixerlistWidget->currentRow()+1);
    if(event->matches(QKeySequence::MoveToPreviousLine))
        MixerlistWidget->setCurrentRow(MixerlistWidget->currentRow()-1);
}

int ModelEdit::gm_moveMix(int idx, bool dir) //true=inc=down false=dec=up
{
    if(idx>MAX_MIXERS || (idx==0 && !dir) || (idx==MAX_MIXERS && dir)) return idx;

    int tdx = dir ? idx+1 : idx-1;
    MixData &src=eeData.mixData[idx];
    MixData &tgt=eeData.mixData[tdx];

    if((src.destCh==0) || (src.destCh>NUM_XCHNOUT) || (tgt.destCh>NUM_XCHNOUT)) return idx;

    if(tgt.destCh!=src.destCh) {
        if ((dir)  && (src.destCh<NUM_XCHNOUT)) src.destCh++;
        if ((!dir) && (src.destCh>0))          src.destCh--;
        return idx;
    }

    //flip between idx and tgt
    MixData temp;
    memcpy(&temp,&src,sizeof(MixData));
    memcpy(&src,&tgt,sizeof(MixData));
    memcpy(&tgt,&temp,sizeof(MixData));

    //do the same for the notes
    QString ix = mixNotes[idx];
    mixNotes[idx].clear();
    mixNotes[idx].append(mixNotes[tdx]);
    mixNotes[tdx].clear();
    mixNotes[tdx].append(ix);


    return tdx;
}

void ModelEdit::moveMixUp()
{
    QList<int> list = createListFromSelected();
    QList<int> highlightList;
    foreach(int idx, list)
        highlightList << gm_moveMix(idx, false);

    updateSettings();
    tabMixes();

    setSelectedByList(highlightList);
}

void ModelEdit::moveMixDown()
{
    QList<int> list = createListFromSelected();
    QList<int> highlightList;
    foreach(int idx, list)
        highlightList << gm_moveMix(idx, true);

    updateSettings();
    tabMixes();

    setSelectedByList(highlightList);
}



void ModelEdit::on_resetCurve_1_clicked()
{
    memset(&eeData.curves5[0],0,sizeof(eeData.curves5[0]));
    updateCurvesTab();
    updateSettings();
    drawCurve();
}

void ModelEdit::on_resetCurve_2_clicked()
{
    memset(&eeData.curves5[1],0,sizeof(eeData.curves5[0]));
    updateCurvesTab();
    updateSettings();
    drawCurve();
}

void ModelEdit::on_resetCurve_3_clicked()
{
    memset(&eeData.curves5[2],0,sizeof(eeData.curves5[0]));
    updateCurvesTab();
    updateSettings();
    drawCurve();
}

void ModelEdit::on_resetCurve_4_clicked()
{
    memset(&eeData.curves5[3],0,sizeof(eeData.curves5[0]));
    updateCurvesTab();
    updateSettings();
    drawCurve();
}

void ModelEdit::on_resetCurve_5_clicked()
{
    memset(&eeData.curves5[4],0,sizeof(eeData.curves5[0]));
    updateCurvesTab();
    updateSettings();
    drawCurve();
}

void ModelEdit::on_resetCurve_6_clicked()
{
    memset(&eeData.curves5[5],0,sizeof(eeData.curves5[0]));
    updateCurvesTab();
    updateSettings();
    drawCurve();
}

void ModelEdit::on_resetCurve_7_clicked()
{
    memset(&eeData.curves5[6],0,sizeof(eeData.curves5[0]));
    updateCurvesTab();
    updateSettings();
    drawCurve();
}

void ModelEdit::on_resetCurve_8_clicked()
{
    memset(&eeData.curves5[7],0,sizeof(eeData.curves5[0]));
    updateCurvesTab();
    updateSettings();
    drawCurve();
}




void ModelEdit::on_resetCurve_9_clicked()
{
    memset(&eeData.curves9[0],0,sizeof(eeData.curves9[0]));
    updateCurvesTab();
    updateSettings();
    drawCurve();
}

void ModelEdit::on_resetCurve_10_clicked()
{
    memset(&eeData.curves9[1],0,sizeof(eeData.curves9[0]));
    updateCurvesTab();
    updateSettings();
    drawCurve();
}

void ModelEdit::on_resetCurve_11_clicked()
{
    memset(&eeData.curves9[2],0,sizeof(eeData.curves9[0]));
    updateCurvesTab();
    updateSettings();
    drawCurve();
}

void ModelEdit::on_resetCurve_12_clicked()
{
    memset(&eeData.curves9[3],0,sizeof(eeData.curves9[0]));
    updateCurvesTab();
    updateSettings();
    drawCurve();
}

void ModelEdit::on_resetCurve_13_clicked()
{
    memset(&eeData.curves9[4],0,sizeof(eeData.curves9[0]));
    updateCurvesTab();
    updateSettings();
    drawCurve();
}

void ModelEdit::on_resetCurve_14_clicked()
{
    memset(&eeData.curves9[5],0,sizeof(eeData.curves9[0]));
    updateCurvesTab();
    updateSettings();
    drawCurve();
}

void ModelEdit::on_resetCurve_15_clicked()
{
    memset(&eeData.curves9[6],0,sizeof(eeData.curves9[0]));
    updateCurvesTab();
    updateSettings();
    drawCurve();
}

void ModelEdit::on_resetCurve_16_clicked()
{
    memset(&eeData.curves9[7],0,sizeof(eeData.curves9[0]));
    updateCurvesTab();
    updateSettings();
    drawCurve();
}


void ModelEdit::safetySwitchesEdited()
{
    for(int i=0; i<NUM_CHNOUT; i++)
    {
        eeData.safetySw[i].swtch = safetySwitchSwtch[i]->currentIndex()-NUM_SWITCHES-1;
        eeData.safetySw[i].val   = safetySwitchValue[i]->value();
    }
    updateSettings();
}


MixData* ModelEdit::setDest(uint8_t dch)
{
    uint8_t i = 0;
    while ((eeData.mixData[i].destCh<=dch) && (eeData.mixData[i].destCh) && (i<MAX_MIXERS)) i++;
    if(i==MAX_MIXERS) return &eeData.mixData[0];

    memmove(&eeData.mixData[i+1],&eeData.mixData[i],
            (MAX_MIXERS-(i+1))*sizeof(MixData) );
    memset(&eeData.mixData[i],0,sizeof(MixData));
    eeData.mixData[i].destCh = dch;
    return &eeData.mixData[i];
}

void ModelEdit::clearMixes(bool ask)
{
    if(ask)
    {
        int res = QMessageBox::question(this,tr("Clear Mixes?"),tr("Really clear all the mixes?"),QMessageBox::Yes | QMessageBox::No);
        if(res!=QMessageBox::Yes) return;
    }
    memset(eeData.mixData,0,sizeof(eeData.mixData)); //clear all mixes
    updateSettings();
    tabMixes();
}

void ModelEdit::clearCurves(bool ask)
{
    if(ask)
    {
        int res = QMessageBox::question(this,tr("Clear Curves?"),tr("Really clear all the curves?"),QMessageBox::Yes | QMessageBox::No);
        if(res!=QMessageBox::Yes) return;
    }
    memset(eeData.curves5,0,sizeof(eeData.curves5)); //clear all curves
    memset(eeData.curves9,0,sizeof(eeData.curves9)); //clear all curves
    updateSettings();
    updateCurvesTab();
    resizeEvent();
}

void ModelEdit::setCurve(uint8_t c, int8_t ar[])
{
    if(c<MAX_CURVE5) //5 pt curve
        for(uint8_t i=0; i<5; i++) eeData.curves5[c][i] = ar[i];
    else  //9 pt curve
        for(uint8_t i=0; i<9; i++) eeData.curves9[c-MAX_CURVE5][i] = ar[i];
}

void ModelEdit::setSwitch(uint8_t idx, uint8_t func, int8_t v1, int8_t v2)
{
    eeData.customSw[idx-1].func = func;
    eeData.customSw[idx-1].v1   = v1;
    eeData.customSw[idx-1].v2   = v2;
}


void ModelEdit::on_plotCB_1_toggled(bool checked)
{
    plot_curve[0] = checked;
    drawCurve();
}

void ModelEdit::on_plotCB_2_toggled(bool checked)
{
    plot_curve[1] = checked;
    drawCurve();
}

void ModelEdit::on_plotCB_3_toggled(bool checked)
{
    plot_curve[2] = checked;
    drawCurve();
}

void ModelEdit::on_plotCB_4_toggled(bool checked)
{
    plot_curve[3] = checked;
    drawCurve();
}

void ModelEdit::on_plotCB_5_toggled(bool checked)
{
    plot_curve[4] = checked;
    drawCurve();
}

void ModelEdit::on_plotCB_6_toggled(bool checked)
{
    plot_curve[5] = checked;
    drawCurve();
}

void ModelEdit::on_plotCB_7_toggled(bool checked)
{
    plot_curve[6] = checked;
    drawCurve();
}

void ModelEdit::on_plotCB_8_toggled(bool checked)
{
    plot_curve[7] = checked;
    drawCurve();
}

void ModelEdit::on_plotCB_9_toggled(bool checked)
{
    plot_curve[8] = checked;
    drawCurve();
}

void ModelEdit::on_plotCB_10_toggled(bool checked)
{
    plot_curve[9] = checked;
    drawCurve();
}

void ModelEdit::on_plotCB_11_toggled(bool checked)
{
    plot_curve[10] = checked;
    drawCurve();
}

void ModelEdit::on_plotCB_12_toggled(bool checked)
{
    plot_curve[11] = checked;
    drawCurve();
}

void ModelEdit::on_plotCB_13_toggled(bool checked)
{
    plot_curve[12] = checked;
    drawCurve();
}

void ModelEdit::on_plotCB_14_toggled(bool checked)
{
    plot_curve[13] = checked;
    drawCurve();
}

void ModelEdit::on_plotCB_15_toggled(bool checked)
{
    plot_curve[14] = checked;
    drawCurve();
}

void ModelEdit::on_plotCB_16_toggled(bool checked)
{
    plot_curve[15] = checked;
    drawCurve();
}

void ModelEdit::ControlCurveSignal(bool flag)
{
  ui->curvePt1_1->blockSignals(flag);
  ui->curvePt2_1->blockSignals(flag);
  ui->curvePt3_1->blockSignals(flag);
  ui->curvePt4_1->blockSignals(flag);
  ui->curvePt5_1->blockSignals(flag);
  ui->curvePt1_2->blockSignals(flag);
  ui->curvePt2_2->blockSignals(flag);
  ui->curvePt3_2->blockSignals(flag);
  ui->curvePt4_2->blockSignals(flag);
  ui->curvePt5_2->blockSignals(flag);
  ui->curvePt1_3->blockSignals(flag);
  ui->curvePt2_3->blockSignals(flag);
  ui->curvePt3_3->blockSignals(flag);
  ui->curvePt4_3->blockSignals(flag);
  ui->curvePt5_3->blockSignals(flag);
  ui->curvePt1_4->blockSignals(flag);
  ui->curvePt2_4->blockSignals(flag);
  ui->curvePt3_4->blockSignals(flag);
  ui->curvePt4_4->blockSignals(flag);
  ui->curvePt5_4->blockSignals(flag);
  ui->curvePt1_5->blockSignals(flag);
  ui->curvePt2_5->blockSignals(flag);
  ui->curvePt3_5->blockSignals(flag);
  ui->curvePt4_5->blockSignals(flag);
  ui->curvePt1_6->blockSignals(flag);
  ui->curvePt2_6->blockSignals(flag);
  ui->curvePt3_6->blockSignals(flag);
  ui->curvePt4_6->blockSignals(flag);
  ui->curvePt5_6->blockSignals(flag);
  ui->curvePt1_7->blockSignals(flag);
  ui->curvePt2_7->blockSignals(flag);
  ui->curvePt3_7->blockSignals(flag);
  ui->curvePt4_7->blockSignals(flag);
  ui->curvePt5_7->blockSignals(flag);
  ui->curvePt1_8->blockSignals(flag);
  ui->curvePt2_8->blockSignals(flag);
  ui->curvePt3_8->blockSignals(flag);
  ui->curvePt4_8->blockSignals(flag);
  ui->curvePt5_8->blockSignals(flag);
  ui->curvePt1_9->blockSignals(flag);
  ui->curvePt2_9->blockSignals(flag);
  ui->curvePt3_9->blockSignals(flag);
  ui->curvePt4_9->blockSignals(flag);
  ui->curvePt5_9->blockSignals(flag);
  ui->curvePt6_9->blockSignals(flag);
  ui->curvePt7_9->blockSignals(flag);
  ui->curvePt8_9->blockSignals(flag);
  ui->curvePt9_9->blockSignals(flag);
  ui->curvePt1_10->blockSignals(flag);
  ui->curvePt2_10->blockSignals(flag);
  ui->curvePt3_10->blockSignals(flag);
  ui->curvePt4_10->blockSignals(flag);
  ui->curvePt5_10->blockSignals(flag);
  ui->curvePt6_10->blockSignals(flag);
  ui->curvePt7_10->blockSignals(flag);
  ui->curvePt8_10->blockSignals(flag);
  ui->curvePt9_10->blockSignals(flag);
  ui->curvePt1_11->blockSignals(flag);
  ui->curvePt2_11->blockSignals(flag);
  ui->curvePt3_11->blockSignals(flag);
  ui->curvePt4_11->blockSignals(flag);
  ui->curvePt5_11->blockSignals(flag);
  ui->curvePt6_11->blockSignals(flag);
  ui->curvePt7_11->blockSignals(flag);
  ui->curvePt8_11->blockSignals(flag);
  ui->curvePt9_11->blockSignals(flag);
  ui->curvePt1_12->blockSignals(flag);
  ui->curvePt2_12->blockSignals(flag);
  ui->curvePt3_12->blockSignals(flag);
  ui->curvePt4_12->blockSignals(flag);
  ui->curvePt5_12->blockSignals(flag);
  ui->curvePt6_12->blockSignals(flag);
  ui->curvePt7_12->blockSignals(flag);
  ui->curvePt8_12->blockSignals(flag);
  ui->curvePt9_12->blockSignals(flag);
  ui->curvePt1_13->blockSignals(flag);
  ui->curvePt2_13->blockSignals(flag);
  ui->curvePt3_13->blockSignals(flag);
  ui->curvePt4_13->blockSignals(flag);
  ui->curvePt5_13->blockSignals(flag);
  ui->curvePt6_13->blockSignals(flag);
  ui->curvePt7_13->blockSignals(flag);
  ui->curvePt8_13->blockSignals(flag);
  ui->curvePt9_13->blockSignals(flag);
  ui->curvePt1_14->blockSignals(flag);
  ui->curvePt2_14->blockSignals(flag);
  ui->curvePt3_14->blockSignals(flag);
  ui->curvePt4_14->blockSignals(flag);
  ui->curvePt5_14->blockSignals(flag);
  ui->curvePt6_14->blockSignals(flag);
  ui->curvePt7_14->blockSignals(flag);
  ui->curvePt8_14->blockSignals(flag);
  ui->curvePt9_14->blockSignals(flag);
  ui->curvePt1_15->blockSignals(flag);
  ui->curvePt2_15->blockSignals(flag);
  ui->curvePt3_15->blockSignals(flag);
  ui->curvePt4_15->blockSignals(flag);
  ui->curvePt5_15->blockSignals(flag);
  ui->curvePt6_15->blockSignals(flag);
  ui->curvePt7_15->blockSignals(flag);
  ui->curvePt8_15->blockSignals(flag);
  ui->curvePt9_15->blockSignals(flag);
  ui->curvePt1_16->blockSignals(flag);
  ui->curvePt2_16->blockSignals(flag);
  ui->curvePt3_16->blockSignals(flag);
  ui->curvePt4_16->blockSignals(flag);
  ui->curvePt5_16->blockSignals(flag);
  ui->curvePt6_16->blockSignals(flag);
  ui->curvePt7_16->blockSignals(flag);
  ui->curvePt8_16->blockSignals(flag);
  ui->curvePt9_16->blockSignals(flag);
}




bool ModelEdit::loadModelFromFile(QString fn)
{
    QString fileName;
    QSettings settings("pipofig", "pipo");


    if(!fn.isEmpty())
    {
        if(!QFileInfo(fn).exists())
        {
            QMessageBox::critical(this, tr("Error"),
                                  tr("Coulden't find %1")
                                  .arg(fn));
            return false;
        }

        fileName = fn;
    }
    else
    {
        //get file to load
        fileName = QFileDialog::getOpenFileName(this,tr("Open"),settings.value("lastDir").toString(),tr(PIPO_FILES_FILTER));
    }

    if (fileName.isEmpty())
        return false;

    settings.setValue("lastDir",QFileInfo(fileName).dir().absolutePath());

    //    quint8 temp[WRITESIZE];


    EEPROMData tmod;

    QDomDocument doc(PIPO_EEPROM_FILE_TYPE);
    QFile file(fileName);
    bool xmlOK = file.open(QIODevice::ReadOnly);
    if(xmlOK)
    {
        xmlOK = doc.setContent(&file);
        if(xmlOK)
        {
            xmlOK = loadModelDataXML(&doc, &tmod);
        }
        file.close();
    }

    if(!xmlOK) //if can't get XML - get HEX file
    {
        quint8 temp[sizeof(EEPROMData)];
        if(!loadiHEX(this, fileName, (quint8*)&temp, sizeof(EEPROMData), ""))
            return false;
        memcpy(&tmod, &temp, sizeof(tmod));
    }

    memcpy(&eeData, &tmod, sizeof(eeData));

    refreshList();
    setModified();

    return true;
}

void ModelEdit::saveModelToFile()
{
    QString fileName;
    QSettings settings("pipofig", "pipo");

    QString modelName = curFile;//QString::fromAscii(tmod.name,sizeof(tmod.name)).trimmed() + ".pipo";

    fileName = QFileDialog::getSaveFileName(this, tr("Save Model As"),settings.value("lastDir").toString() + "/" +modelName,tr(PIPO_FILES_FILTER));


    if (fileName.isEmpty())
        return;

    settings.setValue("lastDir",QFileInfo(fileName).dir().absolutePath());

    QFile file(fileName);

    QDomDocument doc(PIPO_EEPROM_FILE_TYPE);
    QDomElement root = doc.createElement(PIPO_EEPROM_FILE_TYPE);
    doc.appendChild(root);


    QDomElement genData = getModelDataXML(&doc, &eeData);
    root.appendChild(genData);


    if (!file.open(QFile::WriteOnly)) {
        QMessageBox::warning(this, tr("Error"),
                             tr("Cannot write file %1:\n%2.")
                             .arg(fileName)
                             .arg(file.errorString()));
        return;
    }

    QTextStream ts( &file );
    ts << doc.toString();
    file.close();
}

void ModelEdit::newFile()
{
    static int sequenceNumber = 1;

    memset(&eeData, 0, sizeof(eeData));

    isUntitled = true;
    curFile = tr("eepromt%1.pipo").arg(sequenceNumber++);
    setWindowTitle(curFile + "[*]");
}

bool ModelEdit::loadFile(const QString &fileName, bool resetCurrentFile)
{
    if(!QFileInfo(fileName).exists())
    {
        QMessageBox::critical(this, tr("Error"),tr("Unable to find file %1!").arg(fileName));
        return false;
    }


    newFile();

    if(!loadModelFromFile(fileName))
    {
        QMessageBox::critical(this, tr("Error"),
                              tr("Error loading file %1:\n"
                                 "File may be corrupted, old or from a different system.\n"
                                 "You might need to update pipo to read this file.")
                              .arg(fileName));
        return false;
    }

    if(resetCurrentFile) setCurrentFile(fileName);
    return true;


}

bool ModelEdit::save()
{
    if (isUntitled) {
        return saveAs();
    } else {
        return saveFile(curFile);
    }
}

bool ModelEdit::saveAs()
{
    QSettings settings("pipofig", "pipo");
    QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"),settings.value("lastDir").toString() + "/" +curFile,tr(EEPROM_FILES_FILTER));
    if (fileName.isEmpty())
        return false;

    settings.setValue("lastDir",QFileInfo(fileName).dir().absolutePath());
    return saveFile(fileName);
}


void ModelEdit::getNotesFromXML(QDomDocument * qdoc)
{
//    //look for MODEL_DATA with modelNum attribute.
//    //if modelNum = -1 then just pick the first one
//    QDomNodeList ndl = qdoc->elementsByTagName("PIPO_DATA");

//    //cycle through nodes to find correct model number
//    QDomNode k = ndl.at(0);
//    if(k.isNull()) // couldn't find
//        return;

//    QDomNode n = k.toElement().elementsByTagName("Notes").at(0).firstChild();// get all children under "Notes"
//    while (!n.isNull())
//    {
//        if(n.nodeName()=="note")
//        {
//            QDomElement e = n.toElement();
//            int mixNum = QString(e.attribute("mix")).toInt();
//            modelNotes[model_id][mixNum] = e.firstChild().toText().data();
//        }
//        n = n.nextSibling();
//    }
}

void ModelEdit::saveModelToXML(QDomDocument * qdoc, QDomElement * pe)
{
        QDomElement modData = getModelDataXML(qdoc, &eeData);
        pe->appendChild(modData);

        //add notes to model data
//        QDomElement eNotes = qdoc->createElement("Notes");

//        int numNodes = 0;
//        for(int i=0; i<MAX_MIXERS; i++)
//            if(!modelNotes[model_id][i].isEmpty())
//            {
//                numNodes++;
//                QDomElement e = qdoc->createElement("note");
//                QDomText t = qdoc->createTextNode("note");
//                t.setNodeValue(modelNotes[model_id][i]);
//                e.appendChild(t);
//                e.setAttribute("model", model_id);
//                e.setAttribute("mix", i);
//                eNotes.appendChild(e);
//            }

//        if(numNodes)  // add only if non-empty
//            modData.appendChild(eNotes);

}

bool ModelEdit::saveFile(const QString &fileName, bool setCurrent)
{
    QFile file(fileName);

    QDomDocument doc(PIPO_EEPROM_FILE_TYPE);
    QDomElement root = doc.createElement(PIPO_EEPROM_FILE_TYPE);
    doc.appendChild(root);

    QDomElement genData = getModelDataXML(&doc, &eeData);
    root.appendChild(genData);

    if (!file.open(QFile::WriteOnly)) {
        QMessageBox::warning(this, tr("Error"),
                             tr("Cannot write file %1:\n%2.")
                             .arg(fileName)
                             .arg(file.errorString()));
        return false;
    }

    QTextStream ts( &file );
    ts << doc.toString();
    file.close();

    if(setCurrent) setCurrentFile(fileName);
    setModified(false);
    return true;

}

QString ModelEdit::userFriendlyCurrentFile()
{
    return strippedName(curFile);
}

void ModelEdit::closeEvent(QCloseEvent *event)
{
    if (maybeSave()) {
        event->accept();
    } else {
        event->ignore();
    }
}

void ModelEdit::documentWasModified()
{
    setWindowModified(true);
    setModified();
}

bool ModelEdit::maybeSave()
{
    if (fileModified) {
        QMessageBox::StandardButton ret;
        ret = QMessageBox::warning(this, tr("pipo"),
                     tr("'%1' has been modified.\n"
                        "Do you want to save your changes?")
                     .arg(userFriendlyCurrentFile()),
                     QMessageBox::Save | QMessageBox::Discard
                     | QMessageBox::Cancel);
        if (ret == QMessageBox::Save)
            return save();
        else if (ret == QMessageBox::Cancel)
            return false;
    }
    return true;

}

void ModelEdit::setCurrentFile(const QString &fileName)
{
    curFile = QFileInfo(fileName).canonicalFilePath();
    isUntitled = false;
    setModified();
    setWindowModified(false);
    setWindowTitle(userFriendlyCurrentFile() + "[*]");
}

QString ModelEdit::strippedName(const QString &fullFileName)
{
    return QFileInfo(fullFileName).fileName();
}

void ModelEdit::burnTo()  // write to Tx
{
    QMessageBox::StandardButton ret = QMessageBox::question(this, tr("pipo"),
                 tr("Write %1 to EEPROM memory?").arg(strippedName(curFile)),
                 QMessageBox::Yes | QMessageBox::No);

//    optimizeEEPROM();

    if (ret == QMessageBox::Yes)
    {
        burnConfigDialog bcd;
        QString avrdudeLoc = bcd.getAVRDUDE();
        QString tempDir    = QDir::tempPath();
        QString programmer = bcd.getProgrammer();
        QStringList args   = bcd.getAVRArgs();
        QString mcu        = bcd.getMCU();
        if(!bcd.getPort().isEmpty()) args << "-P" << bcd.getPort();

        QString tempFile = tempDir + "/temp.hex";
        //saveFile(tempFile, false);
        saveiHEX(this, tempFile, (quint8 *)&eeData, sizeof(eeData), "");
        if(!QFileInfo(tempFile).exists())
        {
            QMessageBox::critical(this,tr("Error"), tr("Cannot write temporary file!"));
            return;
        }
        QString str = "eeprom:w:" + tempFile + ":i"; // writing eeprom -> MEM:OPR:FILE:FTYPE"

        QStringList arguments;
        arguments << "-c" << programmer << "-p" << mcu << args << "-U" << str;

        avrOutputDialog *ad = new avrOutputDialog(this, avrdudeLoc, arguments, "Write EEPROM To Tx", AVR_DIALOG_SHOW_DONE);
        ad->setWindowIcon(QIcon(":/images/write_eeprom.png"));
        ad->show();
    }
}

bool ModelEdit::saveToFileEnabled()
{
    return true;
}


void ModelEdit::setModified(bool mod)
{
    fileModified = mod;
    setWindowModified(mod);
}





